package com.sojson.util.verifycode;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;

import com.sojson.base.impl.BaseUtilDto;
import com.sojson.util.verifycode.impl.VerifyCodeUtilSimpleImpl;

/**
 * 验证码工具类
 * 
 * @author liu
 * @date 2020-11-02
 */
public class VerifyCodeUtil {

    private static final VerifyCodeUtilInterface VERIFY_CODE_UTIL_INTERFACE = VerifyCodeUtilSimpleImpl.getInstances();

    // =================================================================================================
    // ===========================================验证码范围===============================================
    // =================================================================================================
    /** 使用到Algerian字体，系统里没有的话需要安装字体，去掉了1,0,i,l,o几个容易混淆的字符 */
    public static final char[] VERIFY_CODES = {'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
        'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e',
        'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
    /** 纯数字 */
    public static final char[] NUMBER_CODES = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    /** 算法字符 */
    public static final char[] SYMBOL = {'+', '-', '×', '÷'};
    // =================================================================================================
    // ===========================================验证码后缀===============================================
    // =================================================================================================
    /** 图片验证码的Key */
    public static final String CODE_SUFFIX = "_CODE";
    // =================================================================================================
    // ===========================================验证码样式===============================================
    // =================================================================================================
    /** 验证码的默认长度 */
    public static final int VERIFY_SIZE = VERIFY_CODE_UTIL_INTERFACE.getVerifySize();
    /** 验证码默认有效时间(单位: 毫秒) */
    public static final int DEFAULT_TIME = VERIFY_CODE_UTIL_INTERFACE.getDefaultTime();
    /** 图片的宽度 */
    public static final int WIDTH = VERIFY_CODE_UTIL_INTERFACE.getWidth();
    /** 图片的高度 */
    public static final int HEIGHT = VERIFY_CODE_UTIL_INTERFACE.getHeight();
    /** 字体大小 */
    public static final int FONT_SIZE = VERIFY_CODE_UTIL_INTERFACE.getFontSize();
    /** 字体所占宽度(不是字体宽度) */
    public static final int FONT_WIDTH = VERIFY_CODE_UTIL_INTERFACE.getFontWidth();
    /** 字体底部与边框顶部的距离 */
    public static final int HEIGHT_MARGIN = VERIFY_CODE_UTIL_INTERFACE.getHeightMargin();
    /** 验证码干扰距离 */
    public static final int LINE_HEIGHT = VERIFY_CODE_UTIL_INTERFACE.getLineHeight();
    // =================================================================================================
    // ===========================================验证码类型===============================================
    // =================================================================================================
    /** 随机一种类型 */
    public static final int RANDOM_TYPE = -1;
    /** 有几种类型 */
    public static final int TYPE_COUNT = 2;
    /** 单词数字验证码 */
    public static final int WORD_NUMBER = 0;
    /** 算法验证码 */
    public static final int COMPUTE = 1;
    // =================================================================================================
    // ===========================================验证码类型===============================================
    // =================================================================================================
    /** 字符串验证码 */
    public static final String STR = "STR";
    /** 邮箱验证码 */
    public static final String MAIL = "MAIL";
    /** 短信验证码 */
    public static final String SMS = "SMS";
    /** 图片验证码 */
    public static final String IMG = "IMG";

    /**
     * 使用系统默认字符源生成默认长度的验证码
     * 
     * @return
     */
    public static Verify generateVerifyCode() {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode();
    }

    /**
     * 使用系统默认字符源生成验证码
     * 
     * @param verifySize 验证码长度
     * @return
     */
    public static Verify generateVerifyCode(int verifySize) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(verifySize);
    }

    /**
     * 使用指定源生成默认长度的验证码
     * 
     * @param sources 验证码字符源
     * @return
     */
    public static Verify generateVerifyCode(char[] sources) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(sources);
    }

    /**
     * 使用系统默认字符源生成验证码
     * 
     * @param minSize 验证码最小长度
     * @param maxSize 验证码最大长度
     * @return
     */
    public static Verify generateVerifyCode(int minSize, int maxSize) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(minSize, maxSize);
    }

    /**
     * 使用指定源生成验证码
     * 
     * @param minSize 验证码最小长度
     * @param maxSize 验证码最大长度
     * @param sources 验证码字符源
     * @return
     */
    public static Verify generateVerifyCode(int minSize, int maxSize, char[] sources) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(minSize, maxSize, sources);
    }

    /**
     * 使用指定源生成验证码
     * 
     * @param verifySize 验证码长度
     * @param sources 验证码字符源
     * @return
     */
    public static Verify generateVerifyCode(int verifySize, char[] sources) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(verifySize, sources);
    }

    /**
     * 使用指定源生成验证码
     * 
     * @param sources 验证码字符源
     * @param codeType 验证码类型
     * @return
     */
    public static Verify generateVerifyCode(char[] sources, int codeType) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(sources, codeType);
    }

    /**
     * 使用指定源生成验证码
     * 
     * @param verifySize 验证码长度
     * @param sources 验证码字符源
     * @param codeType 验证码类型
     * @return
     */
    public static Verify generateVerifyCode(int verifySize, char[] sources, int codeType) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCode(verifySize, sources, codeType);
    }

    /**
     * 生成单词数字验证码
     * 
     * @return
     */
    public static Verify generateVerifyCodeByWordNumber() {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCodeByWordNumber();
    }

    /**
     * 生成单词数字验证码
     * 
     * @param verifySize 验证码长度
     * @param sources 验证码字符源
     * @return
     */
    public static Verify generateVerifyCodeByWordNumber(int verifySize, char[] sources) {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCodeByWordNumber(verifySize, sources);
    }

    /**
     * 生成算法验证码
     * 
     * @return
     */
    public static Verify generateVerifyCodeByCompute() {
        return VERIFY_CODE_UTIL_INTERFACE.generateVerifyCodeByCompute();
    }

    /**
     * 获取验证码
     * 
     * @param codePrefix 验证码名称
     * @throws IOException 
     */
    public static Verify getVerifyCode(String verifyCode) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCode(verifyCode);
    }

    /**
     * 清除验证码
     * 
     * @param codePrefix 验证码名称
     * @throws IOException 
     */
    public static void clearVerifyCode(String verifyCode) throws IOException {
        VERIFY_CODE_UTIL_INTERFACE.clearVerifyCode(verifyCode);
    }

    /**
     * 对比验证码
     * 
     * @param codeName 验证码名称
     * @param code 验证码
     * @return
     * @throws IOException 
     */
    public static boolean verifyCode(String verifyCode, String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.verifyCode(verifyCode, code);
    }

    /**
     * 对比验证码
     * 
     * @param verify 验证码
     * @param code 验证码
     * @return
     * @throws IOException 
     */
    public static boolean verifyCode(Verify verify, String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.verifyCode(verify, code);
    }

    /**
     * 对比并清除验证码
     * 
     * @param codeName 验证码名称
     * @param code 验证码
     * @return
     * @throws IOException 
     */
    public static boolean verifyAndClearCode(String verifyCode, String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.verifyAndClearCode(verifyCode, code);
    }

    /**
     * 对比并清除验证码
     * 
     * @param codeName 验证码
     * @param code 验证码
     * @return
     * @throws IOException 
     */
    public static boolean verifyAndClearCode(Verify verify, String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.verifyAndClearCode(verify, code);
    }

    /**
     * 设置验证码名称
     * 
     * @param verifyCodePrefix 验证码前缀
     * @return
     */
    public static String packagingverifyCodeName(String verifyCodePrefix) {
        return VERIFY_CODE_UTIL_INTERFACE.packagingverifyCodeName(verifyCodePrefix);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     */
    public static BufferedImage getVerifyCodeBufferedImage(String code) {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBufferedImage(code);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     */
    public static BufferedImage getVerifyCodeBufferedImage(int width, int height, int fontSize, int fontWidth,
        int heightMargin, String code) {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBufferedImage(width, height, fontSize, fontWidth, heightMargin,
            code);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     */
    public static BufferedImage getVerifyCodeBufferedImage(String code, int lineHeight) {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBufferedImage(code, lineHeight);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     */
    public static BufferedImage getVerifyCodeBufferedImage(int width, int height, int fontSize, int fontWidth,
        int heightMargin, String code, int lineHeight) {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBufferedImage(width, height, fontSize, fontWidth, heightMargin,
            code, lineHeight);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(code);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(String code, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(code, suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(int width, int height, int fontSize, int fontWidth, int heightMargin,
        String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(width, height, fontSize, fontWidth, heightMargin, code);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(int width, int height, int fontSize, int fontWidth, int heightMargin,
        String code, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(width, height, fontSize, fontWidth, heightMargin, code,
            suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(String code, int lineHeight) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(code, lineHeight);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(String code, int lineHeight, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(code, lineHeight, suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(int width, int height, int fontSize, int fontWidth, int heightMargin,
        String code, int lineHeight) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(width, height, fontSize, fontWidth, heightMargin, code,
            lineHeight);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static byte[] getVerifyCodeBytes(int width, int height, int fontSize, int fontWidth, int heightMargin,
        String code, int lineHeight, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeBytes(width, height, fontSize, fontWidth, heightMargin, code,
            lineHeight, suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(code);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(String code, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(code, suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(int width, int height, int fontSize, int fontWidth,
        int heightMargin, String code) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(width, height, fontSize, fontWidth, heightMargin,
            code);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(int width, int height, int fontSize, int fontWidth,
        int heightMargin, String code, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(width, height, fontSize, fontWidth, heightMargin,
            code, suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(String code, int lineHeight) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(code, lineHeight);
    }

    /**
     * 生成验证码图片
     * 
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(String code, int lineHeight, String suffix)
        throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(code, lineHeight, suffix);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(int width, int height, int fontSize, int fontWidth,
        int heightMargin, String code, int lineHeight) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(width, height, fontSize, fontWidth, heightMargin,
            code, lineHeight);
    }

    /**
     * 生成验证码图片
     * 
     * @param width 图片宽度
     * @param height 图片高度
     * @param fontSize 字体大小
     * @param fontWidth 字体所占宽度(不是字体宽度)
     * @param heightMargin 字体底部与底部边框的距离
     * @param code 验证码
     * @param lineHeight 验证码干扰线距离
     * @param suffix 验证码图片的格式
     * @throws IOException 
     */
    public static ByteArrayInputStream getVerifyCodeInputStream(int width, int height, int fontSize, int fontWidth,
        int heightMargin, String code, int lineHeight, String suffix) throws IOException {
        return VERIFY_CODE_UTIL_INTERFACE.getVerifyCodeInputStream(width, height, fontSize, fontWidth, heightMargin,
            code, lineHeight, suffix);
    }

    /**
     * 验证码对象
     * 
     * @author liu
     *
     */
    public static class Verify extends BaseUtilDto implements Serializable {

        /**
         * 
         */
        private static final long serialVersionUID = 8852389606816690862L;

        /** 验证码的名称 */
        private String codeName;
        /** 验证码的帐号(手机号?邮箱号?) */
        private String username;
        /** 验证码 */
        private String code;
        /** 验证码的值 */
        private String value;
        /** 验证码文件的路径 */
        private String url;
        /** 验证码创建的时间 */
        private Date createTime = new Date();

        /** 获取验证码的名称 */
        public String getCodeName() {
            return codeName;
        }

        /** 设置验证码的名称 */
        public void setCodeName(String codeName) {
            this.codeName = codeName;
        }

        /** 获取验证码的帐号(手机号?邮箱号?) */
        public String getUsername() {
            return username;
        }

        /** 设置验证码的帐号(手机号?邮箱号?) */
        public void setUsername(String username) {
            this.username = username;
        }

        /** 获取验证码 */
        public String getCode() {
            return code;
        }

        /** 设置验证码 */
        public void setCode(String code) {
            this.code = code;
        }

        /** 获取验证码的值 */
        public String getValue() {
            return value;
        }

        /** 设置验证码的值 */
        public void setValue(String value) {
            this.value = value;
        }

        /** 获取验证码文件的路径 */
        public String getUrl() {
            return url;
        }

        /** 设置验证码文件的路径 */
        public void setUrl(String url) {
            this.url = url;
        }

        /** 获取验证码创建的时间 */
        public Date getCreateTime() {
            return createTime;
        }

        /** 设置验证码创建的时间 */
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    }

}